package com.hqd.jjvm.instructions.load;

import com.hqd.jjvm.instructions.AbstractInstruction;
import com.hqd.jjvm.instructions.InstructionType;
import com.hqd.jjvm.rtda.JThread;
import com.hqd.jjvm.rtda.obj.JObject;

public class LoadInstruction extends AbstractInstruction {

    public LoadInstruction(JThread jThread) {
        super(jThread);
    }

    @Override
    public void execute(InstructionType instructionType) {

        switch (instructionType) {
            case ILOAD: {
                Integer localVarIndex = parseAndReadValU1();
                pushOperandStackVal(getLocalVarsIntVal(localVarIndex));
                break;
            }
            case LLOAD: {
                Integer localVarIndex = parseAndReadValU1();
                pushOperandStackVal(getLocalVarsLongVal(localVarIndex));
                break;
            }
            case FLOAD: {
                Integer localVarIndex = parseAndReadValU1();
                pushOperandStackVal(getLocalVarsFloatVal(localVarIndex));
                break;
            }
            case DLOAD: {
                Integer localVarIndex = parseAndReadValU1();
                pushOperandStackVal(getLocalVarsDoubleVal(localVarIndex));
                break;
            }
            case ALOAD: {
                Integer localVarIndex = parseAndReadValU1();
                pushOperandStackVal(getLocalVarsRefVal(localVarIndex));
                break;
            }
            case ILOAD_0: {
                pushOperandStackVal(getLocalVarsIntVal(0));
                break;
            }
            case ILOAD_1: {
                pushOperandStackVal(getLocalVarsIntVal(1));
                break;
            }
            case ILOAD_2: {
                pushOperandStackVal(getLocalVarsIntVal(2));
                break;
            }
            case ILOAD_3: {
                pushOperandStackVal(getLocalVarsIntVal(3));
                break;
            }
            case LLOAD_0: {
                pushOperandStackVal(getLocalVarsLongVal(0));
                break;
            }
            case LLOAD_1: {
                pushOperandStackVal(getLocalVarsLongVal(1));
                break;
            }
            case LLOAD_2: {
                pushOperandStackVal(getLocalVarsLongVal(2));
                break;
            }
            case LLOAD_3: {
                pushOperandStackVal(getLocalVarsLongVal(3));
                break;
            }
            case FLOAD_0: {
                pushOperandStackVal(getLocalVarsFloatVal(0));
                break;
            }
            case FLOAD_1: {
                pushOperandStackVal(getLocalVarsFloatVal(1));
                break;
            }
            case FLOAD_2: {
                pushOperandStackVal(getLocalVarsFloatVal(2));
                break;
            }
            case FLOAD_3: {
                pushOperandStackVal(getLocalVarsFloatVal(3));
                break;
            }
            case DLOAD_0: {
                pushOperandStackVal(getLocalVarsDoubleVal(0));
                break;
            }
            case DLOAD_1: {
                pushOperandStackVal(getLocalVarsDoubleVal(1));
                break;
            }
            case DLOAD_2: {
                pushOperandStackVal(getLocalVarsDoubleVal(2));
                break;
            }
            case DLOAD_3: {
                pushOperandStackVal(getLocalVarsDoubleVal(3));
                break;
            }
            case ALOAD_0: {
                pushOperandStackVal(getLocalVarsRefVal(0));
                break;
            }
            case ALOAD_1: {
                pushOperandStackVal(getLocalVarsRefVal(1));
                break;
            }
            case ALOAD_2: {
                pushOperandStackVal(getLocalVarsRefVal(2));
                break;
            }
            case ALOAD_3: {
                pushOperandStackVal(getLocalVarsRefVal(3));
                break;
            }
            case IALOAD: {
                int index = popOperandStackIntVal();
                JObject arrRef = popOperandStackRefVal();
                int[] ints = (int[]) arrRef.getData();
                pushOperandStackVal(ints[index]);
                break;
            }
            case LALOAD: {
                break;
            }
            case FALOAD: {
                break;
            }
            case DALOAD: {
                break;
            }
            case AALOAD: {
                int index = popOperandStackIntVal();
                JObject arrRef = popOperandStackRefVal();
                if (arrRef == null) {
                    throw new NullPointerException();
                }
                JObject[] refs = (JObject[]) arrRef.getData();
                if (refs.length <= index || index < 0) {
                    throw new IndexOutOfBoundsException();
                }
                pushOperandStackVal(refs[index]);
                break;
            }
            case BALOAD: {
                int index = popOperandStackIntVal();
                JObject arrRef = popOperandStackRefVal();
                if (arrRef == null) {
                    throw new NullPointerException();
                }
                byte[] bs = (byte[]) arrRef.getData();
                pushOperandStackVal(bs[index]);
                break;
            }
            case CALOAD: {
                int index = popOperandStackIntVal();
                JObject arrRef = popOperandStackRefVal();
                if (arrRef == null) {
                    throw new NullPointerException();
                }
                char[] cs = (char[]) arrRef.getData();
                pushOperandStackVal(cs[index]);
                break;
            }
            case SALOAD: {
                break;
            }

        }
    }
}
